package com.tao.common.security.service;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.tao.common.creo.constants.CacheConstants;
import com.tao.common.creo.constants.HttpConstants;
import com.tao.common.creo.constants.JwtConstants;
import com.tao.common.redis.service.RedisService;
import com.tao.common.creo.Utils.JwtUtils;
import com.tao.common.creo.domain.LoginUser;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class TokenService {

    @Autowired
    RedisService redisService;

    /**
     *
     * @param UserId 用户的id
     * @param secret    盐值
     * @param identity 用户的身份等级 1 普通用户 2 管理员
     * @return token
     */

    public String creteToken(Long UserId , String niceName, String secret, Integer identity, String headImage) {

        // token 的载荷存储的是用户的userId(唯一标识)
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtConstants.USER_ID, UserId); // 存储用户的id
        String token = JwtUtils.createToken(claims, secret);

        // 接下来需要将用户的信息存储到redis中
        // key 只存储UserId , uuid 存储在Redis中
        String key = CacheConstants.LOGIN_TOKEN_KEY + UserId;

        LoginUser loginUser = new LoginUser();
        loginUser.setIdentity(identity); // 赋值用户权限
        loginUser.setNiceName(niceName); // 用户的昵称
        loginUser.setHeadImage(headImage); // 用户头像
        redisService.setCacheObject(key, loginUser, CacheConstants.EXC, TimeUnit.MINUTES);

        return token;
    }



    /**
     * 从redis获取用户信息
     * @param token
     */
    public LoginUser getLoginUser(String token, String secret) {
        // 删除前缀 Bearer
        if (StrUtil.isNotEmpty(token) && token.startsWith(HttpConstants.PREFIX)) {
            token = token.replaceFirst(HttpConstants.PREFIX, StrUtil.EMPTY);
        }
        Claims claims = getClaims(token, secret);
        if(claims == null) {
            return null;
        }
        return  redisService.getCacheObject(getRedisKey( String.valueOf(getUserId(claims))), LoginUser.class);
    }



    /**
     * 当剩余时间小于360分钟时就更新过期时间
     * @param userId
     */
    public void extendToken(Long userId) {
        String login_token = CacheConstants.LOGIN_TOKEN_KEY + userId; // 拼接出 redis 的 key
        try {
            Long expirationTime = redisService.getExpire(login_token); // 剩余过期时间, 单位分钟
            if(expirationTime > 0 && expirationTime < CacheConstants.HALF) {
                boolean expire = redisService.expire(login_token, CacheConstants.EXC, TimeUnit.MINUTES);
            }
        }catch (Exception e) {
            log.info("更新时间失败, Redis key: {}", login_token);
        }
    }


    /**
     * 获取token信息
     */
    public Claims getClaims(String token, String secret) {
        // 去除前缀
        token = deletePrefix(token);
        Claims claims;
        try {
            claims = JwtUtils.parseToken(token, secret); // 解析令牌, 从令牌中获取用户的唯一标识
            if(claims == null) {
                log.info("解析token:{}, 出现异常", token);
                return null;
            }
        }catch (Exception e) {
            log.info("解析token: {} ,出现异常: {}", token, e);
            return null;
        }

        return claims;
    }

    /**
     * 从 jwt中获取userid
     * @param claims
     */
    public Long getUserId(Claims claims) {
        if(claims == null) return null;
        return Long.valueOf(JwtUtils.getUserId(claims));
    }


    /**
     * 拼接userKey
     * @param userId 用户id
     * @return login_token: userId
     */
    public String getRedisKey(String userId) {
        return CacheConstants.LOGIN_TOKEN_KEY + userId;
    }

    public String getRedisKey(String token, String secret) {
        Claims claims = getClaims(deletePrefix(token), secret);
        if(claims == null) return null;
        Long userId = getUserId(claims);
        if(userId == null) return null;
        return CacheConstants.LOGIN_TOKEN_KEY + userId;
    }

    public String getUUID(Claims claims) {
        if (claims == null) return null;
        return String.valueOf(JwtUtils.getUUID(claims));
    }

    /**
     * 删除前缀 Bearer
     * @param token token
     * @return 删除前缀后的token
     */
    public String deletePrefix(String token) {
        if (StrUtil.isNotEmpty(token) && token.startsWith(HttpConstants.PREFIX)) {
            token = token.replaceFirst(HttpConstants.PREFIX, StrUtil.EMPTY);
        }
        return token;
    }

}
